/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.cjt2325.cameralibrary.listener;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;

import com.cjt2325.cameralibrary.state.CameraMachine;
import com.cjt2325.cameralibrary.util.LogUtil;

import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.FrameConfig;

import ohos.media.recorder.Recorder;

import java.util.Optional;

/**
 * CameraStateCallback Impl
 */
public class CameraStateCallbackImpl extends CameraStateCallback {
    private CameraMachine mMachine;

    private Camera mCamera;
    private Recorder mRecorder;

    public CameraStateCallbackImpl(CameraMachine machine) {
        this.mMachine = machine;
    }

    /**
     * set Recorder
     *
     * @param recorder Recorder
     */
    public void setRecorder(Recorder recorder) {
        this.mRecorder = recorder;
    }

    @Override
    public void onCreated(Camera camera) {
        super.onCreated(camera);
        LogUtil.error(LogUtil.DEFAULT_TAG, "onCreated");
        SurfaceProvider surfaceProvider = mMachine.getView().getSurfaceProvider();
        if (surfaceProvider == null) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onCreated surfaceProvider is null");
            return;
        }
        Optional<SurfaceOps> surfaceOps = surfaceProvider.getSurfaceOps();
        if (surfaceOps == null || !surfaceOps.isPresent()) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onCreated surfaceOps is null");
            return;
        }
        Surface previewSurface = surfaceOps.get().getSurface();
        if (previewSurface == null) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "create camera filed, preview surface is null");
            return;
        }

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "Waiting to be interrupted");
        }

        CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
        cameraConfigBuilder.addSurface(previewSurface);
        cameraConfigBuilder.addSurface(mMachine.getView().getImageReceiver().getRecevingSurface());
        camera.configure(cameraConfigBuilder.build());

        mCamera = camera;
        LogUtil.error(LogUtil.DEFAULT_TAG, "onCreated end");
    }

    @Override
    public void onConfigured(Camera camera) {
        super.onConfigured(camera);
        LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured");
        SurfaceProvider surfaceProvider = mMachine.getView().getSurfaceProvider();
        if (surfaceProvider == null) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured surfaceProvider is null");
            return;
        }
        Optional<SurfaceOps> surfaceOps = surfaceProvider.getSurfaceOps();
        if (surfaceOps == null || !surfaceOps.isPresent()) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured surfaceOps is null");
            return;
        }
        FrameConfig.Builder framePreviewConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
        framePreviewConfigBuilder.addSurface(surfaceOps.get().getSurface());
        if (mRecorder != null) {
            Surface surface = mRecorder.getVideoSurface();
            framePreviewConfigBuilder.addSurface(surface);
        }
        FrameConfig config = framePreviewConfigBuilder.build();
        try {
            // 启动循环帧捕获
            int triggerId = camera.triggerLoopingCapture(config);
        } catch (IllegalArgumentException e) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured IllegalArgumentException e:" + e.getMessage());
        } catch (IllegalStateException e) {
            LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured IllegalStateException e:" + e.getMessage());
        }
        if (mRecorder != null) {
            new EventHandler(EventRunner.getMainEventRunner())
                    .postTask(
                            new Runnable() {
                                @Override
                                public void run() {
                                    mRecorder.start();
                                }
                            });
        }
        LogUtil.error(LogUtil.DEFAULT_TAG, "onConfigured end");
    }

    @Override
    public void onFatalError(Camera camera, int errorCode) {
        super.onFatalError(camera, errorCode);
        LogUtil.error(LogUtil.DEFAULT_TAG, "onFatalError errorCode:" + errorCode);
    }

    /**
     * get Camera
     *
     * @return Camera
     */
    public Camera getCamera() {
        return mCamera;
    }

    /**
     * get Machine
     *
     * @return CameraMachine
     */
    public CameraMachine getMachine() {
        return mMachine;
    }
}
